﻿// owner 蒋家伟

#pragma once
// std
#include <functional>

// jsdk
#include "UniqueId.h"
#include "ElementId.h"
#include "DataSchema_home.h"
#include "Dbg_Warn_Define.h"
#include "TemplateCommonUtils.h"

// jsdk 反射相关
#include "UniqueId.h"
#include "DBVector.h"
#include "DBSet.h"
#include "DBMap.h"
#include "DBUMap.h"
#include "FieldReflectDefine.h"
#include "FieldReflectDeclare.h"
#include "ObjectReflectTemplate.h"
#include "BaseTypeFieldDescriptor.h"
#include "VectorTypeFieldDescriptor.h"
#include "OwnerPtrObjectFieldDescriptor.h"
#include "SetTypeFieldDescriptor.h"
#include "MapTypeFieldDescriptor.h"
#include "UMapTypeFieldDescriptor.h"

namespace jsdk
{
    class DBSchemaObject;
}

using reflectFun = std::function<jsdk::OwnerPtr<jsdk::DBSchemaObject>()>;

#define DBSCHEMAOBJECT_VIRTUAL_FUN_DEFINE(NAMESAPCE, CLASSNAME) \
const jsdk::UniqueId& NAMESAPCE ::CLASSNAME:: getClassId() const\
{\
    return NAMESAPCE :: CLASSNAME :: getReflectUid();\
}\
const std::wstring& NAMESAPCE ::CLASSNAME:: getClassName() const\
{\
    static std::wstring s_className(WSTRING_OF(NAMESAPCE::CLASSNAME));\
    return s_className; \
}\
bool NAMESAPCE ::CLASSNAME::serialize(JsonDocument& jsonDoc, JsonObject& jsonObject) const\
{\
    jsdk::fieldSerialize_iterate fieldSerializeiter(jsonDoc);\
    if(this->fieldSerialize_iterate(fieldSerializeiter))\
    {\
        return jsdk::CommonFieldDescriptor::schemaObjectSerialize(jsonDoc, jsonObject, NAMESAPCE ::CLASSNAME::getClassId(), std::move(fieldSerializeiter.m_Object));\
    }\
    return false;\
}\
bool NAMESAPCE ::CLASSNAME::unserialize(const JsonObject& jsonObject)\
{\
    IFieldReflectManager* pFieldReflectManager = this->getFieldReflectManager();\
    if(pFieldReflectManager == nullptr)\
        return false;\
    return jsdk::ObjectReflectUtils::schemaObjectUnserialize(jsonObject, WSTRING_OF(NAMESAPCE ::CLASSNAME), *pFieldReflectManager);\
}

// 类支持反射的定义
#define OBJECT_REFLECT_DEFINE(NAMESAPCE, CLASSNAME) \
DBSCHEMAOBJECT_VIRTUAL_FUN_DEFINE(NAMESAPCE, CLASSNAME)\
FIELD_REFLECT_DEFINE(NAMESAPCE, CLASSNAME)\
const jsdk::UniqueId& NAMESAPCE :: CLASSNAME :: getReflectUid()\
{\
    static jsdk::UniqueId s_##CLASSNAME##_reflectUId = jsdk::UniqueId::fromWString(NAMESAPCE :: CLASSNAME :: getReflectUidStr());\
    return s_##CLASSNAME##_reflectUId;\
}\
bool NAMESAPCE :: CLASSNAME :: s_##CLASSNAME##_reflect_object_register = jsdk::ObjectReflectUtils::registerReflectClassDescriptor<NAMESAPCE :: CLASSNAME>(WSTRING_OF(NAMESAPCE::CLASSNAME));\
NAMESAPCE :: CLASSNAME :: CLASSNAME()

namespace jsdk
{
    // 序列化反射迭代器
    struct fieldReflect_iterate {
        /// \ brief 非ownerptr包含的版本
        template<typename T>
        void operator()(const T& arg, uint64_t offset, jsdk::IFieldReflectManager* pMgr, const std::wstring& typeName, const std::wstring& varName) const {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pMgr, L"字段反射管理器为空", L"蒋家伟", L"2023-11-29");
            using Type = typename BaseTypeFieldDescriptor<T>;
            pMgr->registerReflectField(NEW_AS_OWNERPTR(Type, varName, offset, typeName));
        }

        /// \ brief owner ptr包裹的版本，被ownptr包裹会偏特化到这个版本
        template<typename T>
        void operator()(const jsdk::OwnerPtr<T>& arg, uint64_t offset, jsdk::IFieldReflectManager* pMgr, const std::wstring& typeName, const std::wstring& varName) const {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pMgr, L"字段反射管理器为空", L"蒋家伟", L"2023-11-29");
            using Type = typename OwnerPtrObjectFieldDescriptor<jsdk::OwnerPtr<T>>;
            pMgr->registerReflectField(NEW_AS_OWNERPTR(Type, varName, offset, typeName));
        }

        template<typename T>
        void operator()(const jsdk::DBvector<T>& arg, uint64_t offset, jsdk::IFieldReflectManager* pMgr, const std::wstring& typeName, const std::wstring& varName) const {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pMgr, L"字段反射管理器为空", L"蒋家伟", L"2023-11-29");
            using Type = typename VectorTypeFieldDescriptor<jsdk::DBvector<T>>;
            pMgr->registerReflectField(NEW_AS_OWNERPTR(Type, varName, offset, typeName));
        }

        template<typename T, typename CP>
        void operator()(const jsdk::DBSet<T, CP>& arg, uint64_t offset, jsdk::IFieldReflectManager* pMgr, const std::wstring& typeName, const std::wstring& varName) const {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pMgr, L"字段反射管理器为空", L"蒋家伟", L"2023-11-29");
            using Type = typename SetTypeFieldDescriptor< jsdk::DBSet<T, CP> >;
            pMgr->registerReflectField(NEW_AS_OWNERPTR(Type, varName, offset, typeName));
        }

        template<typename K, typename V, typename CP>
        void operator()(const jsdk::DBMap<K, V, CP>& arg, uint64_t offset, jsdk::IFieldReflectManager* pMgr, const std::wstring& typeName, const std::wstring& varName) const {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pMgr, L"字段反射管理器为空", L"蒋家伟", L"2023-11-29");
            using Type = typename MapTypeFieldDescriptor< jsdk::DBMap<K, V, CP> >;
            pMgr->registerReflectField(NEW_AS_OWNERPTR(Type, varName, offset, typeName));
        }

        template<typename K, typename V, typename Hash>
        void operator()(const jsdk::DBUMap<K, V, Hash>& arg, uint64_t offset, jsdk::IFieldReflectManager* pMgr, const std::wstring& typeName, const std::wstring& varName) const {
            DBG_WARN_AND_RETURN_VOID_UNLESS(pMgr, L"字段反射管理器为空", L"蒋家伟", L"2023-11-29");
            using Type = typename UMapTypeFieldDescriptor< jsdk::DBUMap<K, V, Hash> >;
            pMgr->registerReflectField(NEW_AS_OWNERPTR(Type, varName, offset, typeName));
        }
    };

    // 序列化迭代器
    struct fieldSerialize_iterate {
        template<typename T>
        bool operator()(const T& arg, const jsdk::IClassFieldDescriptor& descriptor) {
            jsdk::JsonObject object = jsdk::JsonUtils::createObject();

            bool success = descriptor.serialize(m_JsonDoc, object);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(success, L"类别名称: " + descriptor.getTypeName() + L"\n变量名称" + descriptor.getVariableName() + L"流化失败", L"蒋家伟", L"2023-11-30");
            std::string varName = jsdk::StringUtils::toString(descriptor.getVariableName()) ;
            jsdk::JsonUtils::insert(m_JsonDoc, m_Object, varName.c_str(), std::move(object));
            return true;
        }

        fieldSerialize_iterate(JsonDocument& jsonDoc) : 
            m_JsonDoc(jsonDoc), 
            m_Object(jsdk::JsonUtils::createObject()) {
        }
        jsdk::JsonObject m_Object{};
        jsdk::JsonDocument& m_JsonDoc;
    };

    class DATASCHEMA_EXPORT ObjectReflectUtils
    {
    public:
        template<typename T, typename RT = TemplateCommonUtils::Decay_t<T>>
        static OwnerPtr<RT> getObjectReflect()
        {
            static_assert(std::is_same<RT, T>::value, "T类型需要传递基本, 不需要任何修饰符");
            static_assert(std::is_base_of<jsdk::DBSchemaObject, RT>::value, "T类型需要继承IObject");
            return transformOwnerShipAndCast<RT>(ObjectReflectUtils::getObjectReflectImp(RT::getReflectUid(), TemplateCommonUtils::getClassId<RT>()));
        }

        template<typename T>
        static IFieldReflectManager* getFieldReflectManager(T* pClassAddress)
        {
            if (pClassAddress == nullptr)
                return nullptr;
            using type = jsdk::TemplateCommonUtils::Decay_t<T>;
            static_assert(std::is_base_of<jsdk::DBSchemaObject, type>::value, "T类型需要继承IObject");
            static_assert(!std::is_abstract<type>::value, "T不能是纯虚类型");
            return jsdk::ObjectReflectUtils::getFieldReflectManagerImp(type::getReflectUid(), (void*)pClassAddress);
        }

        template<typename T>
        static bool registerReflectClassDescriptor(const std::wstring& classTypeName)
        {
            using type = jsdk::TemplateCommonUtils::Decay_t<T>;
            static_assert(std::is_same<type, T>::value, "T类型需要传递基本, 不需要任何修饰符");
            static_assert(std::is_base_of<jsdk::DBSchemaObject, type>::value, "T类型需要继承IObject");
            static_assert(!std::is_abstract<type>::value, "T不能是纯虚类型");
            auto creator = []() {return NEW_AS_OWNERPTR(type); };
            bool success = jsdk::ObjectReflectUtils::registerReflectClassDescriptorImp(type::getReflectUid(), classTypeName, creator);
            jsdk::fieldReflect_iterate fieldReflectiter;

            /// \ 注册类描述
            creator()->fieldReflect_iterate(fieldReflectiter);
            return success;
        }

        static OwnerPtr<jsdk::DBSchemaObject> getObjectReflectImp(const jsdk::UniqueId& uid, const char* pClassId);

        /// \ brief 对象反流
        /// \ in jsonObject 反流的数据对象
        /// \ in className  类名称
        /// \ in fieldReflectManager 字段管理器
        /// \ return true 表示反流成功
        static bool schemaObjectUnserialize(const JsonObject& jsonObject, const std::wstring& className, IFieldReflectManager& fieldReflectManager);
    private:
        static bool registerReflectClassDescriptorImp(const jsdk::UniqueId& uid, const std::wstring& classTypeName , const reflectFun& fun);
        static jsdk::IFieldReflectManager* getFieldReflectManagerImp(const jsdk::UniqueId& uid, void* pClassAddress);
    };
}
